package com.qian.service.ddj.serviceImpl;

import com.qian.api.ddj.model.Business;
import com.qian.api.ddj.model.Order;
import com.qian.api.ddj.model.PayTypeDict;
import com.qian.api.ddj.model.StatusDict;
import com.qian.api.ddj.service.IBusinessService;
import com.qian.service.ddj.dao.*;
import com.qian.service.ddj.entity.*;
import com.yaowk.api.common.BaseException;
import com.yaowk.service.common.BaseRepository;
import com.yaowk.service.common.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import java.util.*;

@Service
public class BusinessServiceImpl extends BaseServiceImpl<Business, DdjBusiness, Integer> implements IBusinessService {

    @Autowired
    private BusinessGroupRepository businessGroupDao;
    @Autowired
    private ChannelRepository channelDao;
    @Autowired
    private BusinessRepository dao;
    @Autowired
    private UserRepository userDao;
    @Autowired
    private UserBusinessRepository userBusinessDao;
    @Autowired
    private MoneyMapRepository moneyMapDao;
    @Autowired
    private OrderRepository orderDao;
    @Autowired
    private BusinessCardRepository cardBalanceDao;
    @PersistenceContext
    private EntityManager em;

    @Transactional
    public List<Business> findAllBusinessByChannelId(Integer id) {
        Set<DdjBusiness> ddjBusinesses = new HashSet<>();
        DdjChannel channel = channelDao.findOne(id);
        Set<DdjBusinessGroup> ddjBusinessGroupSet = channel.getBusinessGroups();
        for (DdjBusinessGroup ddjBusinessGroup : ddjBusinessGroupSet) {
            ddjBusinesses.addAll(ddjBusinessGroup.getBusinesses());
        }
        return entity2Model(ddjBusinesses);
    }

    public List<Business> findBusinessByUserId(Integer userId) {
        DdjUser ddjUser = userDao.findOne(userId);
        return entity2Model(ddjUser.getBusinesses());
    }

    @Transactional
    public List<Business> findAllBusinessByGroupId(Integer id) {
        DdjBusinessGroup ddjBusinessGroup = businessGroupDao.findOne(id);
        return entity2Model(ddjBusinessGroup.getBusinesses());
    }

    @Transactional
    public void stop(Collection<Integer> ids) {
        if (!CollectionUtils.isEmpty(ids)) {
            for (Integer id : ids) {
                DdjBusiness ddjBusiness = dao.findOne(id);
                ddjBusiness.setStatus(StatusDict.CLOSE);
                dao.save(ddjBusiness);
            }
        }
    }

    @Override
    @Transactional
    public Business chooseBusiness(Order order, boolean loop) {
        if (loop) {
            List<DdjUserBusiness> userBusinesses = userBusinessDao.findByUserIdOrderByVersion(order.getUserId());
            DdjUserBusiness ddjUserBusiness = null;
            DdjBusiness ddjBusiness = null;
            // 选择满足支付方式的支付渠道
            for (DdjUserBusiness dubs : userBusinesses) {
                boolean choose = false;
                DdjBusiness ddjBusiness1 = dubs.getBusiness();
                if (!ddjBusiness1.getStatus().equals(StatusDict.NORMAL)) {
                    continue;
                }
                if (!(ddjBusiness1.getBeginMoney().compareTo(order.getRealAmount()) <= 0 && ddjBusiness1.getEndMoney().compareTo(order.getRealAmount()) >= 0)) {
                    continue;
                }
                DdjBusinessGroup ddjBusinessGroup = ddjBusiness1.getBusinessGroup();
                if (PayTypeDict.ALI_CODE.equals(order.getPayType()) && ddjBusinessGroup.getAllowAliCode().equals(StatusDict.NORMAL)) {
                    choose = true;
                } else if (PayTypeDict.ALI_WAP.equals(order.getPayType()) && ddjBusinessGroup.getAllowAliWap().equals(StatusDict.NORMAL)) {
                    choose = true;
                } else if (PayTypeDict.WX_CODE.equals(order.getPayType()) && ddjBusinessGroup.getAllowWxCode().equals(StatusDict.NORMAL)) {
                    choose = true;
                } else if (PayTypeDict.WX_H5.equals(order.getPayType()) && ddjBusinessGroup.getAllowWxH5().equals(StatusDict.NORMAL)) {
                    choose = true;
                } else if (PayTypeDict.QUICK_BANK.equals(order.getPayType()) && ddjBusinessGroup.getAllowQuickBank().equals(StatusDict.NORMAL)) {
                    choose = true;
                } else if (PayTypeDict.QQ.equals(order.getPayType()) && ddjBusinessGroup.getAllowQq().equals(StatusDict.NORMAL)) {
                    choose = true;
                } else if (PayTypeDict.JD.equals(order.getPayType()) && ddjBusinessGroup.getAllowJd().equals(StatusDict.NORMAL)) {
                    choose = true;
                } else if (PayTypeDict.QQ_WAP.equals(order.getPayType()) && ddjBusinessGroup.getAllowQqWap().equals(StatusDict.NORMAL)) {
                    choose = true;
                } else if (PayTypeDict.CODE_BANK.equals(order.getPayType()) && ddjBusinessGroup.getAllowCodeBank().equals(StatusDict.NORMAL)) {
                    choose = true;
                }
                if (choose) {
                    ddjBusiness = ddjBusiness1;
                    ddjUserBusiness = dubs;
                    break;
                }
            }

            if (!ObjectUtils.isEmpty(ddjBusiness)) {
//                Query query = em.createNativeQuery("update ddj_user_business set version = version + 1 where business_id = ?1 and user_id = ?2 and version = ?3");
//                query.setParameter(1, ddjUserBusiness.getBusiness().getId());
//                query.setParameter(2, ddjUserBusiness.getUser().getId());
//                query.setParameter(3, ddjUserBusiness.getVersion());
//                int result = query.executeUpdate();
                ddjUserBusiness.setVersion(ddjUserBusiness.getVersion() + 1);
                try {
                    userBusinessDao.save(ddjUserBusiness);
                } catch (Exception e) {
                    throw new RuntimeException("支付通道竞争失败");
                }
                if (ObjectUtils.isEmpty(ddjBusiness)) {
                    throw new RuntimeException("2");
                }
                // 检查金额转换配置
                DdjMoneyMap moneyMap = new DdjMoneyMap();
                moneyMap.setGroupId(ddjBusiness.getBusinessGroup().getId());
                moneyMap.setBeforeMoney(order.getAmount());
                DdjMoneyMap mapResult = moneyMapDao.findOne(Example.of(moneyMap));
                if (!ObjectUtils.isEmpty(mapResult)) {
                    DdjOrder ddjOrder = new DdjOrder();
                    ddjOrder.setId(order.getId());
                    ddjOrder.setRealAmount(mapResult.getEndMoney());
                    orderDao.save(ddjOrder);
                }
                return entity2model(ddjBusiness);
            } else {
                throw new RuntimeException("1");
            }
        }
        throw new RuntimeException("0");
    }

    @Override
    @Transactional
    public Set<Byte> findPayTypeByUserId(Integer userId) {
        Set<Byte> allSet = new HashSet<>();
        DdjUser ddjUser = userDao.findOne(userId);

        if (!ObjectUtils.isEmpty(ddjUser)) {
            Set<DdjBusiness> ddjBusinesses = ddjUser.getBusinesses();

            if (!CollectionUtils.isEmpty(ddjBusinesses)) {
                for (DdjBusiness ddjBusiness : ddjBusinesses) {
                    DdjBusinessGroup ddjBusinessGroup = ddjBusiness.getBusinessGroup();
                    if (ddjBusinessGroup.getAllowAliCode().equals(StatusDict.NORMAL)) {
                        allSet.add(PayTypeDict.ALI_CODE);
                    }
                    if (ddjBusinessGroup.getAllowAliWap().equals(StatusDict.NORMAL)) {
                        allSet.add(PayTypeDict.ALI_WAP);
                    }
                    if (ddjBusinessGroup.getAllowJd().equals(StatusDict.NORMAL)) {
                        allSet.add(PayTypeDict.JD);
                    }
                    if (ddjBusinessGroup.getAllowQq().equals(StatusDict.NORMAL)) {
                        allSet.add(PayTypeDict.QQ);
                    }
                    if (ddjBusinessGroup.getAllowQuickBank().equals(StatusDict.NORMAL)) {
                        allSet.add(PayTypeDict.QUICK_BANK);
                    }
                    if (ddjBusinessGroup.getAllowWxCode().equals(StatusDict.NORMAL)) {
                        allSet.add(PayTypeDict.WX_CODE);
                    }
                    if (ddjBusinessGroup.getAllowWxH5().equals(StatusDict.NORMAL)) {
                        allSet.add(PayTypeDict.WX_H5);
                    }
                }
            }
        }
        return allSet;
    }

    @Override
    @Transactional
    public List<Business> findByZFB() {
        DdjChannel ddjChannel = new DdjChannel();
        ddjChannel.setCode("selfZFB");
        ddjChannel = channelDao.findOne(Example.of(ddjChannel));
        List<DdjBusiness> businesses = new ArrayList<>();
        if (isNotEmpty(ddjChannel)) {
            for (DdjBusinessGroup ddjBusinessGroup : ddjChannel.getBusinessGroups()) {
                for (DdjBusiness ddjBusiness : ddjBusinessGroup.getBusinesses()) {
                    businesses.add(ddjBusiness);
                }
            }
        }
        return entity2Model(businesses);
    }

    @Override
    @Transactional
    public Integer getCodeOfSelfZFB(Integer id) {
        DdjBusiness ddjBusiness = dao.findOne(id);
        String code = ddjBusiness.getBackup1();
        Integer codeId = Integer.valueOf(code) + 1;
        int result = dao.updateCode(id, codeId.toString(), code);
        if (result != 1) {
            throw new BaseException("竞争失败");
        }
        return codeId;
    }

    @Transactional
    public void start(Collection<Integer> ids) {
        if (!CollectionUtils.isEmpty(ids)) {
            for (Integer id : ids) {
                DdjBusiness ddjBusiness = dao.findOne(id);
                ddjBusiness.setStatus(StatusDict.NORMAL);
                dao.save(ddjBusiness);
                List<DdjUserBusiness> ddjUserBusinesses = userBusinessDao.findByBusinessId(id);
                for (DdjUserBusiness ddjUserBusiness : ddjUserBusinesses) {
                    userBusinessDao.setVersionByUserId(ddjUserBusiness.getUserId());
                }
            }
        }
    }

    @Override
    public Business save(Business model) {
        if (model.isNew()) {
            model = simpleSave(model);
        } else { // 修改
            DdjBusiness ddjBusiness = dao.findOne(model.getId());
            if (isNotEmpty(model.getSecretKey()))
                ddjBusiness.setSecretKey(model.getSecretKey());
            if (isNotEmpty(model.getAccount()))
                ddjBusiness.setAccount(model.getAccount());
            if (isNotEmpty(model.getBackup1()))
                ddjBusiness.setBackup1(model.getBackup1());
            if (isNotEmpty(model.getBackup2()))
                ddjBusiness.setBackup2(model.getBackup2());
            if (model.getBackup3() != null)
                ddjBusiness.setBackup3(model.getBackup3());
            if (model.getBackup4() != null)
                ddjBusiness.setBackup4(model.getBackup4());
            if (isNotEmpty(model.getBackup5()))
                ddjBusiness.setBackup5(model.getBackup5());
            if (isNotEmpty(model.getBeginMoney()))
                ddjBusiness.setBeginMoney(model.getBeginMoney());
            if (isNotEmpty(model.getEndMoney()))
                ddjBusiness.setEndMoney(model.getEndMoney());
            if (isNotEmpty(model.getName()))
                ddjBusiness.setName(model.getName());
            if (isNotEmpty(model.getStatus()))
                ddjBusiness.setStatus(model.getStatus());
            if (isNotEmpty(model.getRemark()))
                ddjBusiness.setRemark(model.getRemark());
            if (isNotEmpty(model.getBusinessCardId())) {
                DdjBusinessCard ddjBusinessCard = new DdjBusinessCard();
                ddjBusinessCard.setId(model.getBusinessCardId());
                ddjBusiness.setBusinessCard(ddjBusinessCard);
            }

            model = entity2model(dao.save(ddjBusiness));
        }

        return model;
    }


    protected BaseRepository<DdjBusiness, Integer> getDao() {
        return dao;
    }

    protected DdjBusiness model2Entity(Business model) {
        DdjBusiness ddjBusiness = new DdjBusiness();
        ddjBusiness.setStatus(model.getStatus());
        ddjBusiness.setAccount(model.getAccount());
        ddjBusiness.setBackup1(model.getBackup1());
        ddjBusiness.setBackup2(model.getBackup2());
        ddjBusiness.setBackup3(model.getBackup3());
        ddjBusiness.setBackup4(model.getBackup4());
        ddjBusiness.setBackup5(model.getBackup5());
        ddjBusiness.setBeginMoney(model.getBeginMoney());
        ddjBusiness.setEndMoney(model.getEndMoney());
        DdjBusinessGroup businessGroup = new DdjBusinessGroup();
        businessGroup.setId(model.getGroupId());
        ddjBusiness.setBusinessGroup(businessGroup);
        ddjBusiness.setId(model.getId());
        ddjBusiness.setSecretKey(model.getSecretKey());
        ddjBusiness.setName(model.getName());
        ddjBusiness.setRemark(model.getRemark());
        if (isNotEmpty(model.getBusinessCardId())) {
            DdjBusinessCard ddjBusinessCard = new DdjBusinessCard();
            ddjBusinessCard.setId(model.getBusinessCardId());
            ddjBusiness.setBusinessCard(ddjBusinessCard);
        }
        return ddjBusiness;
    }

    protected Business entity2model(DdjBusiness entity) {
        Business business = new Business();
        business.setStatus(entity.getStatus());
        business.setAccount(entity.getAccount());
        business.setBackup1(entity.getBackup1());
        business.setBackup2(entity.getBackup2());
        business.setBackup3(entity.getBackup3());
        business.setBackup4(entity.getBackup4());
        business.setBackup5(entity.getBackup5());
        business.setBeginMoney(entity.getBeginMoney());
        business.setEndMoney(entity.getEndMoney());
        business.setGroupId(entity.getBusinessGroup().getId());
        business.setId(entity.getId());
        business.setSecretKey(entity.getSecretKey());
        business.setName(entity.getName());
        business.setRemark(entity.getRemark());
        business.setBusinessCardId(entity.getBusinessCardId());
        return business;
    }
}
